package com.study.thread.juc.lock;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/*
    CyclicBarrier：是一个循环屏障，在代码中插入一个屏障点，也就是一个阻塞点，使用await()方法将线程阻塞，等待最后一个线程调用被阻塞线程都被唤醒，其实也是一个计时器
        当一个线程在代码中调用await()，如果不是最后一个线程调用的会被阻塞，第一个线程调用完被阻塞了，第二个线程调用了以后会阻塞，第三个线程调用后会把所有的全部释放
        此时里面的计数器将会重置，重新开始计算循环屏障，下次有线程调用也是需要三个线程
            await()：当线程调用会被阻塞，内部维护了一个计数器，当计数器为0时唤醒所有被阻塞的线程，计时器重新从设置的开始，线程可以重新阻塞
       总结：此同步类与CountDownLatch相似，但是CDL使用只能一次，没办法第二次使用（如果需要的话第二次重新new才可以使用），两者的await()都是不满足要求
            将当前线程阻塞，当满足要求后（CDL是所有线程调用了countDown()后计数器为0满足要求，CB是所有线程调用了await()后计数器为0了，满足要求），CDL只会唤醒一个阻塞线程，
            CyclicBarrier则会唤醒所有阻塞线程起来运行，并重置当前计数器，从而达到循环使用,CyclicBarrier每次唤醒线程前的时候执行初始化传入的Runnable运行run方法！
 */
public class CyclicBarrier2Demo {
    private static CyclicBarrier cyclicBarrier1 = new CyclicBarrier(3, () -> {
        System.out.println("task notifyAll");
    });

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            try {
                System.out.println("the 1");
                cyclicBarrier1.await();
                System.out.println("the 2");
                cyclicBarrier1.await();
                System.out.println("the 3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                System.out.println("the 1");
                cyclicBarrier1.await();
                System.out.println("the 2");
                cyclicBarrier1.await();
                System.out.println("the 3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

        }).start();
        new Thread(() -> {

            try {
                System.out.println("the 1");
                cyclicBarrier1.await();
                System.out.println("the 2");
                cyclicBarrier1.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("the 3");
        }).start();
    }
}
